package com.emep.emeptime.service;

import com.emep.emeptime.entity.*;
import com.emep.emeptime.model.ApiData;
import com.emep.emeptime.repository.AreaAqiMoniterRepository;
import com.emep.emeptime.repository.DataAqiInfoRepository;
import com.emep.emeptime.utils.DateUtils;
import com.emep.emeptime.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import java.util.*;

/**
 * @author wangcc
 * @Description: 城市数据监测业务层
 * @date 2018/3/278:56
 * @version V1.0
 */
@Service
@Slf4j
public class AreaAqiMoniterService {


    /**
     * 城市监测表持久层
     */
    @Resource
    private AreaAqiMoniterRepository areaAqiMoniterRepository;
    /**
     * aqi数据表业务层
     */
    @Resource
    private DataAqiInfoRepository dataAqiInfoRepository;
    /**
     * aqi管控表业务层
     */
    @Resource
    private AQIControlInfoService aqiControlInfoService;
    /**
     *aqi标准业务层
     */
    @Resource
    private SysAqiInfoService sysAqiInfoService;
    /**
     * 行政区划业务层
     */
    @Resource
    private SysAreaInfoService sysAreaInfoService;
    /**
     * 标记颜色业务
     */
    @Resource
    private SysAqiLevelService sysAqiLevelService;

    String areaCode = "";
     /**
     * 新增城市监测数据
     * @param apiData
     * @return
     * @throws
     */
    public void save(List<ApiData> apiData) {
        //获取行政区划code
         areaCode = getAreaId(apiData);
        if (apiData != null && !apiData.isEmpty()) {
            //去掉不运行的监控站
            Iterator<ApiData> iter = apiData.iterator();
            while (iter.hasNext()) {
                ApiData str = iter.next();
                if (str.getPosition_name().equals("澳瑞特")) {
                    iter.remove();
                    break;
                }
            }
            select(apiData);
            for (ApiData apiData1 : apiData) {
                //添加城市的监控数据
                if (apiData1.getArea().equals("长治") && apiData1.getPosition_name() == null) {
                    CreatAreaAqi(apiData1);
                //添加国控监测站数据
                } else {
                    creatDataAqi(apiData1);
                }
            }
        }
    }

    /**
     * 添加城市数据
     * @return
     */
    public void CreatAreaAqi(ApiData apiData1){
        //存放城市监测aqi数据
        AreaAqiMoniter areaAqiMoniter = new AreaAqiMoniter();
        areaAqiMoniter.setAqi(String.valueOf(apiData1.getAqi()));
        areaAqiMoniter.setAreaId(areaCode);
        areaAqiMoniter.setSo2(String.valueOf(apiData1.getSo2()));
        areaAqiMoniter.setCity(apiData1.getArea());
        areaAqiMoniter.setCo(String.valueOf(apiData1.getCo()));
        areaAqiMoniter.setLevel(getNumber(String.valueOf(apiData1.getAqi())));
        areaAqiMoniter.setNo2(String.valueOf(apiData1.getNo2()));
        areaAqiMoniter.setO31h(String.valueOf(apiData1.getO3()));
        areaAqiMoniter.setO38h(String.valueOf(apiData1.getO3_8h()));
        areaAqiMoniter.setPm10(String.valueOf(apiData1.getPm10()));
        areaAqiMoniter.setPm25(String.valueOf(apiData1.getPm2_5()));
        double dfs = Double.valueOf(apiData1.getPm2_5()) / 35 +
                Double.valueOf(apiData1.getPm10()) / 70 +
                Double.valueOf(apiData1.getSo2()) / 60 +
                Double.valueOf(apiData1.getNo2()) / 40 +
                Double.valueOf(apiData1.getCo()) / 4 +
                Double.valueOf(apiData1.getO3_8h()) / 100;
        areaAqiMoniter.setCompositeIndex(String.format("%.2f", dfs));
        areaAqiMoniter.setPrimaryPollutant(apiData1.getPrimary_pollutant());
        String start = apiData1.getTime_point().replace("T", " ").replace("Z", "");
        areaAqiMoniter.setUpdate(String.valueOf(DateUtils.dateToUnixTimestamp((start))));
        try {

            AreaAqiMoniter areaAqiMoniter1 = areaAqiMoniterRepository.save(areaAqiMoniter);
            if (areaAqiMoniter1 != null && !areaAqiMoniter1.getId().equals("")) {
                log.info("【城市监测数据添加成功】时间：{} id:{}", new Date(), areaAqiMoniter1.getId());
            }
        } catch (Exception e) {
            log.error(e.getLocalizedMessage());
        }
    }


    /**
     *  添加监测站数据
     * @param apiData1
     * @return
     */
    public void creatDataAqi(ApiData apiData1){
        DataAqiInfo dataAqiInfo = new DataAqiInfo();
        //空气质量等级
        dataAqiInfo.setQualityId(getLevl(apiData1.getQuality()));
        dataAqiInfo.setO3(String.valueOf(apiData1.getO3()));
        dataAqiInfo.setPm10(String.valueOf(apiData1.getPm10()));
        dataAqiInfo.setPm25(String.valueOf(apiData1.getPm2_5()));
        //行政区划
        dataAqiInfo.setAreaId(areaCode);
        dataAqiInfo.setQualityCode(apiData1.getQuality());
        dataAqiInfo.setCo(String.valueOf(apiData1.getCo()));
        //aqi
        dataAqiInfo.setAqi(String.valueOf(apiData1.getAqi()));
        //二氧化碳
        dataAqiInfo.setSo2(String.valueOf(apiData1.getSo2()));
        //数据时间
        String start = apiData1.getTime_point().replace("T", " ").replace("Z", "");
        dataAqiInfo.setTimePoint(String.valueOf(DateUtils.dateToUnixTimestamp(start)));
        //站点名字
        dataAqiInfo.setPositionName(apiData1.getPosition_name());
        //计算综合指数 6项相加
        double dfs = Double.valueOf(apiData1.getPm2_5()) / 35 +
                     Double.valueOf(apiData1.getPm10()) / 70 +
                     Double.valueOf(apiData1.getSo2()) / 60 +
                     Double.valueOf(apiData1.getNo2()) / 40 +
                     Double.valueOf(apiData1.getCo()) / 4 +
                     Double.valueOf(apiData1.getO3_8h()) / 100;
        dataAqiInfo.setCompositeIndex(String.format("%.2f", dfs));
        dataAqiInfo.setNo2(String.valueOf(apiData1.getNo2()));
        dataAqiInfo.setPrimaryPollutant(apiData1.getPrimary_pollutant());
        try {
            DataAqiInfo dataAqiInfo1 = dataAqiInfoRepository.save(dataAqiInfo);
            if (dataAqiInfo1 != null && !StringUtils.isEmpty(dataAqiInfo1.getId())) {
                log.info(" 【长治市{}监测站数据添加成功】时间：{} id: {}", dataAqiInfo1.getPositionName(), new Date(), dataAqiInfo1.getId());
            }
        }catch (Exception e){
            log.error(e.getLocalizedMessage());
        }
    }

    /**
     * 报警判断
     * @param apiDataList
     */
    public void  select(List<ApiData> apiDataList){
        HashMap<String,SysAqiInfo> dataBeanHashMap = new HashMap<String,SysAqiInfo>(16);
        //获取所有标准值
        List<SysAqiInfo> dataAqiInfos = sysAqiInfoService.getEquipmentMoniterList();
        if (dataAqiInfos != null && !dataAqiInfos.isEmpty()){
            for(SysAqiInfo sysAqiInfo:dataAqiInfos){
                dataBeanHashMap.put(sysAqiInfo.getAqi(),sysAqiInfo);
            }
        }
        Collections.sort(dataAqiInfos);
        //不同的api对应不同的标准值
        for(ApiData dataBean :apiDataList){
            if (!StringUtils.isEmpty(String.valueOf(dataBean.getAqi()))){
                double api = Double.valueOf(dataBean.getAqi());
                for(SysAqiInfo dataAqiInfo:dataAqiInfos){
                    if(api <= Double.valueOf(dataAqiInfo.getAqi()) ){
                        SysAqiInfo sysAqiInfo =  dataBeanHashMap.get(dataAqiInfo.getAqi());
                        judgeMonitr(sysAqiInfo,dataBean);
                        break;
                    }else{
                        continue;
                    }
                }
            }
        }
    }


    /**
     * 判断api等级
     * @param api api数值
     * @return
     */
    public String getNumber(String api){
        String reslt = "";
        if (Double.valueOf(api) < 50) {
            reslt = "1";
        } else if ((Double.valueOf(api) > 50 && (Double.valueOf(api) < 100))) {
            reslt = "2";
        } else if ((Double.valueOf(api) > 100 && (Double.valueOf(api) < 150))) {
            reslt = "3";
        } else if ((Double.valueOf(api) > 150 && (Double.valueOf(api) < 200))) {
            reslt = "4";
        } else if ((Double.valueOf(api) > 200 && (Double.valueOf(api) < 300))) {
            reslt = "5";
        } else {
            reslt = "6";
        }
        return reslt;
    }


    /**
     * 超标记录
     * @param sysAqiInfo 标准值
     * @param apiData    监测数据值
     */
    public void judgeMonitr(SysAqiInfo sysAqiInfo,ApiData apiData){
        //数据时间
        String start = apiData.getTime_point().replace("T", " ").replace("Z", "");
        //报警站点的名字
        String  PositionName  = apiData.getPosition_name();
        if (Double.valueOf(apiData.getPm2_5_24h()) >  Double.valueOf(sysAqiInfo.getPm25_24())){
            addAQIControlInfo(sysAqiInfo.getPm25_24(),"pm2.5",areaCode,sysAqiInfo.getPm25_24(),PositionName,start);
        }
        if (Double.valueOf(apiData.getPm10_24h()) >  Double.valueOf(sysAqiInfo.getPm10_24())){
            addAQIControlInfo(sysAqiInfo.getPm10_24(),"pm1.0",areaCode,sysAqiInfo.getPm10_24(),PositionName,start);
        }
        if (Double.valueOf(apiData.getSo2()) >  Double.valueOf(sysAqiInfo.getSo2())){
            addAQIControlInfo(sysAqiInfo.getSo2(),"so2",areaCode,sysAqiInfo.getSo2(),PositionName,start);
        }
        if (Double.valueOf(apiData.getNo2()) >  Double.valueOf(sysAqiInfo.getNo2())){
            addAQIControlInfo(sysAqiInfo.getNo2(),"no2",areaCode,sysAqiInfo.getNo2(),PositionName,start);
        }
        if (Double.valueOf(apiData.getCo()) >  Double.valueOf(sysAqiInfo.getCo())){
            addAQIControlInfo(sysAqiInfo.getCo(),"co",areaCode,sysAqiInfo.getCo(),PositionName,start);
        }
        if (Double.valueOf(apiData.getO3_8h()) >  Double.valueOf(sysAqiInfo.getO3())){
            addAQIControlInfo(sysAqiInfo.getO3(),"o3",areaCode,sysAqiInfo.getO3_8(),PositionName,start);
        }
    }


    /**
     * 插入异常数据
     * @param sysAqiInfo    标准值
     * @param pollutant     因子
     * @param areaId        行政区划id
     * @param pollutantData 因子数值
     * @param positionName  站点名字
     * @param timePoint     数据时间
     */
    public void addAQIControlInfo(String sysAqiInfo,String pollutant, String areaId,String pollutantData,String positionName,String timePoint){

        AqiControlInfo aqiControlInfo = aqiControlInfoService.save(new AqiControlInfo(sysAqiInfo,pollutant,areaId,pollutantData,positionName,timePoint));
        if (aqiControlInfo != null && ! StringUtils.isEmpty(aqiControlInfo.getId())){
            log.info("【 行政区划id：{}{}监测站因子报警数据添加成功】 ：{}*************",areaId,positionName);
        }else{
            log.info("【 行政区划id：{}{}监测站因子报警数据添加失败 】 ：{}*************",areaId,positionName);
        }
    }

    /**
     * 获取行政区划code
     * @param name
     * @return
     */
    public String getAreaId(List<ApiData> name){
        String areaCode = "";
        try {
            SysAreaInfo sysAreaInfo = sysAreaInfoService.findAreaByAreaName("%" + name.get(0).getArea() + "%");
            if(sysAreaInfo != null ) {

                areaCode = sysAreaInfo.getAreaCode();
            }
        }catch (Exception e){
            log.error(e.getLocalizedMessage());
        }
        return areaCode;
    }

    /**
     *  获取颜色 id
     * @param AeraName
     * @return
     */
    public String getLevl(String AeraName) {
        String id = "";
        try {
            SysAqiLevel sysAqiLevel = sysAqiLevelService.findAreaByAreaName(AeraName);
            if (sysAqiLevel != null) {
                id = String.valueOf(sysAqiLevel.getColor());
            }
        } catch (Exception e) {
            log.error(e.getLocalizedMessage());
        }

        return id;
    }


    /**
     * 根据开始结束时间查询数据
     * @param start
     * @param end
     */
    public List<AreaAqiMoniter> findall(String start ,String end){
        List<AreaAqiMoniter> areaAqiMoniters = null;
        try {
            areaAqiMoniters = areaAqiMoniterRepository.findAll(new Specification<AreaAqiMoniter>(){
                @Override
                public javax.persistence.criteria.Predicate toPredicate(Root<AreaAqiMoniter> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
                    //大于或等于传入时间
                    javax.persistence.criteria.Predicate p1 = criteriaBuilder.greaterThanOrEqualTo(root.get("update").as(String.class), start);
                    //小于或等于传入时间
                    javax.persistence.criteria.Predicate p2 = criteriaBuilder.lessThanOrEqualTo(root.get("update").as(String.class), end);
                    query.where(criteriaBuilder.and(p1,p2));
                    return query.getRestriction();
                }
            });
        }catch (Exception e){
            log.error(e.getLocalizedMessage());
        }
        return areaAqiMoniters;
    }

}
